package com.leo.chapter08;

import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;

/**
 *
 * @author xuexiaolei
 * @version 2017年10月18日
 */
public class ConcurrentPuzzleSolver<P, M> {
    private final Puzzle<P, M> puzzle;
    private final ExecutorService exec;
    private final ConcurrentMap<P, Boolean> seen;
    final ValueLatch<Node<P, M>> solution = new ValueLatch<>();

    public ConcurrentPuzzleSolver(Puzzle<P, M> puzzle, ExecutorService exec, ConcurrentMap<P, Boolean> seen) {
        this.puzzle = puzzle;
        this.exec = exec;
        this.seen = seen;
    }

    public List<M> solve() throws InterruptedException{
        try {
            P p = puzzle.initialPosition();
            exec.execute(newTask(p, null, null));
            //阻塞直到线程找到答案
            Node<P, M> value = solution.getValue();
            return (value==null)? null : value.asMoveList();
        }finally {
            exec.shutdown();
        }
    }

    private Runnable newTask(P p, M m, Node<P, M> n) {
        return new SolverTasK(p, m, n);
    }

    class SolverTasK extends Node<P, M> implements Runnable{

        public SolverTasK(P pos, M move, Node<P, M> prev) {
            super(pos, move, prev);
        }

        @Override public void run() {
            //已经找打答案或者已经遍历了这个位置
            if (solution.isSet() || seen.putIfAbsent(pos, true) != null ){ return; }

            if (puzzle.isGoal(pos)){
                solution.setValue(this);
            }else {
                for (M m : puzzle.legalMoves(pos)){
                    exec.execute(newTask(puzzle.move(pos, m), m, this));
                }
            }
        }
    }
}
